import { WireData } from '@renderer/api'
import { useFocusObject } from '@renderer/utils/useFocusObject'
import {
  Box3,
  BoxGeometry,
  CatmullRomCurve3,
  DoubleSide,
  Group,
  Mesh,
  MeshBasicMaterial,
  MeshPhongMaterial,
  Object3D,
  Vector3
} from 'three'
import { TunnelGeometry } from '@renderer/utils/TunnelGeometry.js'
import { useViewportStore } from '@renderer/stores/viewport'
import { storeToRefs } from 'pinia'
import { useActiveObject } from '@renderer/stores/activeObject'
import { nextTick, Ref } from 'vue'
import emiter from '@renderer/utils/mitt'
import { useHistory } from '@renderer/utils/useHistory'
import { Operation } from 'three-bvh-csg'
import { CSS2DObject } from 'three/examples/jsm/Addons'

export interface Coordinates extends Vector3 {
  _dragClass?: string
}
// 巷道
export interface Roadway {
  name: string
  coordinates: Coordinates[]
  closed: boolean
}
// 操作类型
export type OperationType = 'add' | 'edit'
// 设备
export interface equipment {
  equipmentType: string
  equipmentList: []
  equipmentId: string
}
export interface Equipment {
  id?: string
  name: string
  detailDtos: equipment[]
  coordinates: Vector3
}
const { focusObject } = useFocusObject()
export const useAddTools = () => {
  const activeObjectStore = useActiveObject()
  const { activeShallowRef }: { activeShallowRef: Ref<Object3D> } = storeToRefs(activeObjectStore)
  const viewportStore = useViewportStore()
  const { publicGroup } = storeToRefs(viewportStore)

  const { commitHistory } = useHistory()
  let baseInfo
  // 修改中心点位置
  function updateCenterPoint(mesh: Mesh) {
    mesh.geometry.computeBoundingBox()
    const box3 = new Box3()
    box3.expandByObject(mesh)
    const center = new Vector3(0)
    box3.getCenter(center)
    mesh.position.copy(center)
    mesh.geometry.center()
  }
  // 名字为name的分组时否存在，不存在就创建并加入 publicGroup
  function hasGroup(name: string, created = true) {
    if (!publicGroup.value) return
    let group = publicGroup.value?.children.find((item) => item.name === name)
    if (!group && created) {
      group = new Group()
      group.name = name
      publicGroup.value?.add(group)
    }
    return group
  }
  // 收缩坐标的位数，节约性能
  function $zoomCoordinate(coordinate: Vector3) {
    return new Vector3(coordinate.x, coordinate.y, coordinate.z)
    // return new Vector3(
    //   coordinate.x - baseInfo.xDrawString,
    //   coordinate.y,
    //   coordinate.z - baseInfo.zDrawString
    // )
  }
  // 新增巷道
  function addRoadway(type: OperationType, data: Roadway, closed: boolean) {
    // 创建mesh
    const vecs = data.coordinates.map((item) => {
      return $zoomCoordinate(item)
    })

    const path = new CatmullRomCurve3(vecs)
    const geometry = new TunnelGeometry(path, TunnelGeometry.pathToUMapping(path, 3, 0.3), closed)
    let material = new MeshPhongMaterial({ color: 0xffffff, side: DoubleSide })
    let userData = {
      type: 'roadway',
      customData: {}
    }
    if (type === 'edit') {
      material = activeShallowRef.value.material.clone()
      userData = {
        ...activeShallowRef.value.userData
      }
    }
    const tube = new Operation(geometry, material)
    tube.uuid = data.tunnelId
    tube.userData = userData
    tube.name = data.name
    // 修改中心点
    updateCenterPoint(tube)

    const group = hasGroup('巷道')
    group.add(tube)
    // 加入场景，通知相关控件
    if (type === 'edit') {
      const Object3D = activeShallowRef.value
      activeObjectStore.setActiveVO(undefined)
      Object3D?.parent?.remove(Object3D)
    }
    activeObjectStore.setActiveVO(tube)
    publicGroup.value?.add(group)
  }
  // 将导线数据生成巷道后加入场景
  function loadWireToScene(data: WireData) {
    baseInfo = data.baseInfo
    data.wireItems.forEach((item) => {
      addRoadway(
        'add',
        {
          name: item.tunnelName,
          tunnelId: item.tunnelId,
          coordinates: item.pointVos
        },
        false
      )
    })
    nextTick(() => {
      emiter.emit('viewChange')
      commitHistory('导入导线数据', 'import')
      const group = hasGroup('巷道')
      if (group) {
        focusObject(group)
      }
    })
  }

  // 新增设备
  function editEquipment(data: Equipment) {
    // 创建mesh
    const vecs = $zoomCoordinate(data.coordinates)
    const material =
      activeShallowRef.value?.material.clone() ||
      new MeshBasicMaterial({ color: 0x0ff000, side: DoubleSide })
    const userData = {
      // ...activeShallowRef.value?.userData,
      type: 'equipment',
      detailDtos: data.detailDtos
    }
    const geometry = new BoxGeometry(8, 8, 8)
    const box = new Mesh(geometry, material)
    box.uuid = data.id
    box.position.copy(vecs)
    box.name = data.name
    box.userData = userData
    // 修改中心点
    updateCenterPoint(box)
    // 修改名称，加入场景，通知相关控件

    const group = hasGroup('设备')

    group.add(box)
    if (activeShallowRef.value) {
      const Object3D = activeShallowRef.value
      activeObjectStore.setActiveVO(undefined)
      Object3D?.parent?.remove(Object3D)
      activeObjectStore.setActiveVO(box)
      nextTick(() => {
        emiter.emit('viewChange')
        commitHistory(`修改设备${data.name}`, 'edit')
      })
    } else {
      nextTick(() => {
        emiter.emit('viewChange')
        commitHistory(`添加设备${data.name}`, 'add')
      })
    }
    const label = createdLabel(data.name, data.name)
    label.name = data.name
    box.add(label)
  }
  // 创建CSS2D节点
  function createdLabel(index: number | string, name: string) {
    const lableDiv = document.createElement('div')
    lableDiv.textContent = index
    lableDiv.style.color = '#fff'
    lableDiv.style.fontSize = '16px'
    lableDiv.setAttribute('name', name)
    const label = new CSS2DObject(lableDiv)
    return label
  }
  // 删除CSS2D节点
  function deleteLabel(name: string) {
    const css2DRendererDiv = document.getElementsByClassName('css2DRenderer')[0]
    for (let i = css2DRendererDiv.children.length - 1; i >= 0; i--) {
      if (css2DRendererDiv.children[i].textContent === name) {
        css2DRendererDiv.removeChild(css2DRendererDiv.children[i])
      }
    }
  }

  return {
    hasGroup,
    addRoadway,
    loadWireToScene,
    editEquipment,
    updateCenterPoint,
    createdLabel,
    deleteLabel
  }
}
